package Export;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.biojava3.ws.alignment.qblast.BlastAlignmentParameterEnum;
import org.biojava3.ws.alignment.qblast.BlastOutputParameterEnum;
import org.biojava3.ws.alignment.qblast.BlastProgramEnum;
import org.biojava3.ws.alignment.qblast.NCBIQBlastAlignmentProperties;
import org.biojava3.ws.alignment.qblast.NCBIQBlastOutputProperties;
import org.biojava3.ws.alignment.qblast.NCBIQBlastService;

import DataModel.Sequence;

/**
 * This class exports sequences from selected {@link Sequence}s and executes an
 * online blastn
 * 
 * @author Stefan Lorenz<br>
 * <br>
 *         26.11.2012
 */
public class BlastThread extends Thread {

	File blastOut;
	ArrayList<Sequence> sequenceList;

	public BlastThread(File blastOut, ArrayList<Sequence> sequenceList) {
		this.sequenceList = sequenceList;
		this.blastOut = blastOut;
		this.start();
	}

	@Override
	public void run() {
		super.run();
		// Code : http://biojava.org/wiki/BioJava:CookBook3:NCBIQBlastService
		NCBIQBlastService service = new NCBIQBlastService();

		// set alignment options
		NCBIQBlastAlignmentProperties props = new NCBIQBlastAlignmentProperties();
		props.setBlastProgram(BlastProgramEnum.blastn);
		props.setBlastDatabase("nr");

		// set output options
		NCBIQBlastOutputProperties outputProps = new NCBIQBlastOutputProperties();
		outputProps.setOutputOption(BlastOutputParameterEnum.ALIGNMENTS, "1");

		try {
			FileWriter writer = new FileWriter(blastOut);
			for (int i = 0; i < this.sequenceList.size(); i++) {
				if (this.sequenceList.get(i).getSequence() == "" || this.sequenceList.get(i).getSequence() == "null" || this.sequenceList.get(i).getSequence() == null) {
					System.out.println("No query sequence...skipping feature");
					continue;
				}
				String rid = null; // blast request ID
				BufferedReader reader = null;

				// send blast request and save request id

				rid = service.sendAlignmentRequest(this.sequenceList.get(i).getSequence(), props);
				props.setAlignmentOption(BlastAlignmentParameterEnum.ENTREZ_QUERY, this.sequenceList.get(i).getHeader());
				// wait until results become available. Alternatively, one can
				// do other computations/send other alignment requests
				System.out.print("Blast: Waiting for results.");

				while (!service.isReady(rid)) {
					System.out.print(".");
					Thread.sleep(5000);
				}
				// read results when they are ready
				InputStream in = service.getAlignmentResults(rid, outputProps);
				reader = new BufferedReader(new InputStreamReader(in));

				// write blast output to specified file
				String line;
				while ((line = reader.readLine()) != null) {
					writer.write(line + System.getProperty("line.separator"));
				}

				// delete given alignment results from blast server (optional
				// operation)

				try {
					String url = "http://blast.ncbi.nlm.nih.gov/Blast.cgi?CMD=Get&VIEW_RESULTS=FromRes&RID="+rid+"&QUERY_INDEX=0";
					java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
				} catch (java.io.IOException e) {
					System.out.println(e.getMessage());
				}
				// service.sendDeleteRequest(rid);
				reader.close();
			}
			writer.flush();
			writer.close();
			System.out.println("\nSaving query results in file " + blastOut.getAbsolutePath());
		} catch (Exception e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
}
